// ignore_for_file: prefer_typing_uninitialized_variables, avoid_print, non_constant_identifier_names

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:io';
import 'dart:convert';

// UDP连接读取设备信息
class UdpSocketUtil {
  late RawDatagramSocket rawDatagramSocket;

  static Future<Datagram?> getDeviceInfo() async {
    var DESTINATION_ADDRESS = InternetAddress("10.10.100.10");
    var CONNECT_DATA =
        Uint8List.fromList([0xAA, 0x01, 0xAA, 0xBB, 0xCC, 0xDD, 0x94]);
    Datagram? result;

    await RawDatagramSocket.bind(InternetAddress.anyIPv4, 58121).then(
      (RawDatagramSocket udpSocket) async {
        udpSocket.broadcastEnabled = true;
        //给设备发送信息
        udpSocket.send(CONNECT_DATA, DESTINATION_ADDRESS, 58121);
        //监听设备回复信息
        await udpSocket.listen((e) {
          Datagram? dg = udpSocket.receive();
          if (dg != null) {
            /* for (var data in dg.data) {
              print(data.toRadixString(16));
            } */
            result = dg;
            //print(result != null ? result!.data.length : '00000');
            udpSocket.close();
          }
        }).asFuture();

        ///牛逼！解决异步中套异步,否则在调用时直接抛出resulut（null）
      },
    );
    //print(result != null ? result!.data.length : '00000');
    return result;
  }
}

// TCP/IP连接
class TcpClient<T> {
  late Socket _socket;
  late Stream<String> _stream;
  late List<int> _dataList;
  var candata; //不给定类型稍后确定

  List<Function> messageListeners = [];

  Future<void> connect(
    String host,
    int port,
  ) async {
    try {
      _socket = await Socket.connect(host, port);
      //cast<List<int>>()将返回的数据转为List<int>类型
      //transform(utf8.decoder)编码转换，字节流转字符串流
      //LineSplitter()按行切割
      /* _stream = _socket
          .cast<List<int>>()
          .transform(utf8.decoder)
          .transform(const LineSplitter()); */

      _socket.listen(_onReceivedMsg,
          onError: _onError, onDone: _onDone, cancelOnError: false);

      print('Connect to $host:$port success.');
    } catch (e) {
      print('Connect to $host:$port failed: $e');
      rethrow;
    }
  }

  void addMessageListener(Function listener) {
    messageListeners.add(listener);
  }

  void handleMessage(message) {
    for (Function listener in messageListeners) {
      listener.call(message);
    }
  }

  _onReceivedMsg(event) {
    //print(event);
    handleMessage(event);
    //数据帧校验
    /* _check(event);
    List<int> data = event;
    //从数据包中拿到can报文或can事件
    _dataList = data.sublist(4, data.length - 1);
    final buffer = ByteData.sublistView(Uint8List.fromList(_dataList));
    //0-can报文，1-can事件
    final de = (buffer.getUint8(7) & 0x80) >> 7;
    if (de == 0) {
      candata = EthCanMsg.fromBytes(_dataList);
    } else if (de == 1) {
      //事件类型 0-接收错误帧 1-发送错误帧  2-总线状态帧
      final evetType = (buffer.getUint8(6) & 0xE0) >> 5;
      if (evetType == 2) {
        candata = EthCanStatusFrame.fromBytes(_dataList);
      } else {
        candata = EthErrFrame.fromBytes(_dataList);
      }
    }

    print(_dataList);
    candata = EthCanMsg.fromBytes(_dataList);

    handleMessage(candata); */
  }

  _onError(e) {
    print("Socket _onError callback $e");
  }

  _onDone() {
    print("Socket _onDone callback");
    //handleMessage(event);
  }

  Future<void> send(data) async {
    _socket.add(data);
  }

  Future<void> close() async {
    await _socket.close();
  }
}

//TCP连接
class TCPClient {
  String serverAddress;
  int port;
  Socket? socket;

  Function? onConnect;
  Function? onDisconnect;

  List<Function> messageListeners = [];

  TCPClient({required this.serverAddress, required this.port});

  void connect({Function? onConnect, Function? onDisconnect}) async {
    this.onConnect = onConnect;
    this.onDisconnect = onDisconnect;

    try {
      socket = await Socket.connect(serverAddress, port);
      onConnect?.call();
      socket?.listen((List<int> data) {
        handleMessage(data);
      }, onDone: () {
        disconnect();
      });
    } catch (e) {
      print(e);
    }
  }

  void disconnect() {
    if (socket != null) {
      socket!.destroy();
      socket = null;
      onDisconnect?.call();
    }
  }

  /* void sendMessage(String message) {
    if (_isConnected()) {
      socket!.write(message);
    }
  } */

  void addMessageListener(Function listener) {
    messageListeners.add(listener);
  }

  void removeMessageListener(Function listener) {
    messageListeners.remove(listener);
  }

  /* bool _isConnected() {
    return socket != null && socket!.isConnected();
  } */

  void handleMessage(message) {
    for (Function listener in messageListeners) {
      listener.call(message);
    }
  }
}
